﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using lopet.data;
using lopet.data.Repositories;
using lopet.Repositories;
using System.IO;

namespace DiffisionWithDecomposition
{
    class Program
    {
        private static StreamWriter _streamWiter;

        static void Main(string[] args)
        {
            //Thread t = new Thread(() => MainLoop());

            //////ShannonsMutualInformation.MutualInformation(63, 87, 87, 61);

            //t.Start();

            SimParameters.DecompositionEnabled = false;
            SimParameters.T_s = 60000000;
            SimParameters.SimDuration = SimParameters.T_s * 10000;

            //MainLoop();

            SimParameters.DecompositionEnabled = true;

            for (long k = 4000000; k >= 4000000; k = k / 2)
            {
                SimParameters.MoleculeHalfLife = k;
                SimParameters.NumberOfMolecules = 10;
                SimParameters.T_s = 100000;
                SimParameters.XCoordinateOfCellPosition = 11;
                SimParameters.SimDuration = SimParameters.T_s * 10000;

                MainLoop();

                //for (int i = 0; i < 8; i++)
                //{
                //    MainLoop();
                //    SimParameters.T_s -= 40;
                //    SimParameters.SimDuration = SimParameters.T_s * 1000;
                //}
            }

            //SimParameters.MoleculeHalfLife = 50;
            //SimParameters.T_s = 100;
            //SimParameters.SimDuration = SimParameters.T_s * 1000;
            //MainLoop();
            
            //for (int i = 0; i < 20; i++)
            //{
            //    PrintHistogramsToFile();
            //    SimParameters.MoleculeHalfLife += 100;
            //}
        }
        
        private static void RecordStuff(Communication c)
        {
            _streamWiter.WriteLine("!"+c.Cell.NumberOfAbsorbedMolecules);
            c.Cell.NumberOfAbsorbedMolecules = 0;

            Simulation.Instance.EnqueueEvent(
                new Event(Time.Instance.GetTimeAfterNanoSeconds(100000), () => RecordStuff(c)));
        }

        public static void MainLoop()
        {
            _streamWiter = new StreamWriter(String.Format("Logs\\ D={0}, N={1}, Dec={2}, HL={3}.txt, T_s={4}, Duration = {5}, TimeStep = {6}, RecordTimes = {7}.txt", SimParameters.XCoordinateOfCellPosition,
                SimParameters.NumberOfMolecules, SimParameters.DecompositionEnabled, SimParameters.MoleculeHalfLife, SimParameters.T_s, SimParameters.SimDuration, SimParameters.StepSize, 0), true);

            Simulation.Instance.NewSimulationInstance();
            
            var communication = new Communication();
            communication._streamWiter = _streamWiter;
            communication.SendOneBit(SimParameters.NumberOfMolecules, SimParameters.T_s);

            //RecordStuff(communication);

            while (Simulation.Instance.EndCondition == false)
            {
                Simulation.Instance.DequeueEvent();
            }

            _streamWiter.Flush();
            _streamWiter.Close();

            //WriteStuff(_streamWiter, communication);
        }

        private static void WriteStuff(StreamWriter sw, Communication communication)
        {            
            var mu = ShannonsMutualInformation.MutualInformation(communication.NumberOf0sSent, communication.NumberOf1sSent,
                    communication.NumberOf1sCorrectlyReceived, communication.NumberOf0sCorrectlyReceived);

            sw.WriteLine("NumberOfZerosSent = " + communication.NumberOf0sSent);
            sw.WriteLine("NumberOfOnesSent = " + communication.NumberOf1sSent);
            sw.WriteLine("NumberOfOnesCorrectlyReceived = " + communication.NumberOf1sCorrectlyReceived);
            sw.WriteLine("NumberOfZerosCorrectlyReceived = " + communication.NumberOf0sCorrectlyReceived);

            sw.WriteLine("I = " + mu);
            sw.WriteLine("threshold = " + SimParameters.DetectionThreshold);

            sw.Flush();
            
            Console.WriteLine("threshold = " + SimParameters.DetectionThreshold + ", I = " + mu);

        }       
 
        private static void ReadComplete(string s)
        {
        }
    }
}
